www.gusucode.com > 基于Visual C++高级界面特效制作百例源码程序 > 基于Visual C++高级界面特效制作百例源码程序/code/char23/FontsEnumTest/WizFontsEnumerator.cpp

    // WizFontsEnumerator.cpp: implementation of the CWizFontsEnumerator class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "WizFontsEnumerator.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

namespace
{
UCHAR TTDefaults[] = { 8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72 };
const int TTDefaultsSize =  sizeof(TTDefaults)/sizeof(TTDefaults[0]);
}
//////////////////////////////////////////////////////////////////////

CWizFontsEnumerator::Font::Font(const LOGFONT& lf, DWORD fontType, LPCTSTR Script)
	: m_Name(lf.lfFaceName) ,  m_bItalics(false), m_bBold(false), 
	  m_bUnderline(false),  m_bRegular(false),
	  m_dwFontType(fontType),  m_bInited(false)
{
	if (Script && *Script)
		AddScript(Script);
}

void CWizFontsEnumerator::Font::operator=(const Font& f)
{
	m_Name		= f.m_Name		;
	m_bItalics	= f.m_bItalics	; 
	m_bBold		= f.m_bBold		; 
	m_bUnderline= f.m_bUnderline;
	m_bRegular	= f.m_bRegular;
	m_dwFontType= f.m_dwFontType;

	m_Script.RemoveAll();
	for (int i = 0; i < f.m_Script.GetSize(); i++)
		m_Script.Add(f.m_Script[i]);

	m_sizes.SetSize(f.m_sizes.GetSize());
	for (i = 0; i < f.m_sizes.GetSize(); i++)
		m_sizes[i] = f.m_sizes[i];

	m_bInited = f.m_bInited;
}

struct Font_EnumStep
{
	Font_EnumStep(CWizFontsEnumerator::Font& f, CDC& dc)
		: rTHIS(f) , r_dc(dc) 
		{
		cyPixelsPerInch = dc.GetDeviceCaps(LOGPIXELSY);
		}

	CWizFontsEnumerator::Font& rTHIS;
	CDC& r_dc;
	int	cyPixelsPerInch;
};

int CALLBACK DetailsEnumProc (const ENUMLOGFONTEX *lpelfe, const NEWTEXTMETRICEX *lpntme, unsigned long FontType, LPARAM lParam) 
{
	Font_EnumStep* p = reinterpret_cast<Font_EnumStep*>(lParam);
	/*
	CWizFontsEnumerator::Font* pTHIS = reinterpret_cast<CWizFontsEnumerator::Font*>(lParam);
	return pTHIS->DoEnumStep (lpelfe, lpntme, FontType);
	*/
	return p->rTHIS.DoEnumStep (lpelfe, lpntme, FontType, *p);
}

int CWizFontsEnumerator::Font::DoEnumStep (const ENUMLOGFONTEX *lpelf, const NEWTEXTMETRICEX *lpntm, unsigned long FontType, Font_EnumStep& data)
{
	ASSERT(&(data.rTHIS) == this);

	if (FontType & TRUETYPE_FONTTYPE)
	{
		if (!(lpntm->ntmTm.ntmFlags & (NTM_BOLD | NTM_ITALIC)))
			{
			TRACE("\n\tFont %s add regular", lpelf->elfLogFont.lfFaceName);
			m_bRegular = true;
			}

		if (lpntm->ntmTm.ntmFlags & NTM_ITALIC)
			{
			TRACE("\n\tFont %s add Italics", lpelf->elfLogFont.lfFaceName);
			m_bItalics = true;
			}

		if (lpntm->ntmTm.ntmFlags & NTM_BOLD)
			{
			TRACE("\n\tFont %s add Bold", lpelf->elfLogFont.lfFaceName);
			m_bBold = true;
			}
	}
	else
	{
		if (FontType & RASTER_FONTTYPE)
		{
			int height = lpntm->ntmTm.tmHeight - lpntm->ntmTm.tmInternalLeading;
			int size_pp = MulDiv(height, 72, data.cyPixelsPerInch); //, height);
			TRACE("\n\tFont %s add size %d", lpelf->elfLogFont.lfFaceName, size_pp);
			AddSize(size_pp, height);
		}

		if (lpelf->elfLogFont.lfWeight >= FW_BOLD && lpelf->elfLogFont.lfItalic)
			{
			TRACE("\n\tFont %s add bold & italics", lpelf->elfLogFont.lfFaceName);
			m_bItalics = true;
			m_bBold = true;
			}
		else if (lpelf->elfLogFont.lfWeight >= FW_BOLD)
			{
			TRACE("\n\tFont %s add bold", lpelf->elfLogFont.lfFaceName);
			m_bBold = true;
			}
		else if (lpelf->elfLogFont.lfItalic)
			{
			TRACE("\n\tFont %s add italics", lpelf->elfLogFont.lfFaceName);
			m_bItalics = true;
			}
		else
			{
			TRACE("\n\tFont %s add regular", lpelf->elfLogFont.lfFaceName);
			m_bRegular = true;
			}
	}

	return 1;
	
}

void CWizFontsEnumerator::Font::DoInit() 
{
	// Init flags
	m_bRegular = m_bItalics = m_bBold = m_bUnderline = false;

	// Init for enumeration
	CClientDC dc(NULL);
	LOGFONT lf;
	memset (&lf, 0, sizeof(lf));
	lf.lfCharSet	= DEFAULT_CHARSET;
	strcpy(lf.lfFaceName, m_Name);
	Font_EnumStep temp(const_cast<Font&>(*this), dc);
	// Enumeration procedure
	EnumFontFamiliesEx (dc.m_hAttribDC, &lf, (FONTENUMPROC)::DetailsEnumProc, reinterpret_cast<LPARAM>(&temp), 0);
	// Finish init:
	m_bUnderline = true; // Always availible so far
	// Allow for "synthesized" italic && bold variants
	if (m_bRegular)
		m_bItalics = m_bBold = true;
}

void CWizFontsEnumerator::Font::Initialize() const
{
	if (m_bInited)
		return;
	const_cast<Font*>(this)->DoInit();
	m_bInited = true;
}


void CWizFontsEnumerator::Font::FillSizes(CWordArray& sizes) const
{
	sizes.SetSize(0);
	if (m_dwFontType != RASTER_FONTTYPE)
		{
		sizes.SetSize(TTDefaultsSize);
		for (int i = 0; i < TTDefaultsSize; i++)
			sizes[i] = TTDefaults[i];
		}
	else
		{
		Initialize();
		sizes.SetSize(m_sizes.GetSize());
		for (int i = 0; i < m_sizes.GetSize(); i++)
			sizes[i] = m_sizes[i];
		}
}

bool CWizFontsEnumerator::Font::CanBeItalics	() const
{
	Initialize();
	return m_bItalics;
}

bool CWizFontsEnumerator::Font::CanBeBold		() const
{
	Initialize();
	return m_bBold;
}

bool CWizFontsEnumerator::Font::CanBeUnderline	() const
{
	Initialize();
	return m_bUnderline;
}

bool CWizFontsEnumerator::Font::CanBeRegular	() const
{
	Initialize();
	return m_bRegular;
}

bool CWizFontsEnumerator::Font::MustBeRegular	() const
{
	Initialize();
	return (m_bRegular && !(m_bItalics || m_bUnderline || m_bBold));
}

bool CWizFontsEnumerator::Font::MustBeItalics	() const
{
	Initialize();
	return (m_bItalics && !(m_bRegular /*|| m_bUnderline || m_bBold*/));
}

bool CWizFontsEnumerator::Font::MustBeBold	() const
{
	Initialize();
	return (m_bBold && !(m_bRegular /*|| m_bItalics  || m_bUnderline*/));
}

bool CWizFontsEnumerator::Font::MustBeUnderline	() const
{
	Initialize();
	return false;// (m_bUnderline && !(m_bRegular || m_bItalics || m_bBold));
}


void CWizFontsEnumerator::Font::AddSize(int pp_size, int lf_height)
{
	m_sizes.Add(WORD(pp_size));
}

void CWizFontsEnumerator::Font::AddScript(LPCTSTR Script)
{ 
	m_Script.Add(Script);
}

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CWizFontsEnumerator::CWizFontsEnumerator()
{
}

CWizFontsEnumerator::~CWizFontsEnumerator()
{

}

int	CWizFontsEnumerator::DoEnumStep (const ENUMLOGFONTEX *lpelfe, const NEWTEXTMETRICEX *lpntme, unsigned long FontType)
{
	CString script = lpelfe->elfScript;

TRACE("\nFont %s", lpelfe->elfLogFont.lfFaceName);

	// If font exists yet
	int nFont = FindFont(lpelfe->elfLogFont.lfFaceName);
	if (nFont >= 0)
		{
		m_aFonts.ElementAt(nFont).AddScript(script);

TRACE(" Add script %s", (LPCTSTR)script);

		return 1;
		}
	// add font to list
	Font f (lpelfe->elfLogFont, FontType, script);
	int i = m_aFonts.Add(f);

	if (i < 0)
		{ ASSERT(0); AfxThrowMemoryException(); }

TRACE(" Script %s", (LPCTSTR)script);

	return 1;
}

int CALLBACK EnumProc (const ENUMLOGFONTEX *lpelfe, const NEWTEXTMETRICEX *lpntme, unsigned long FontType, LPARAM lParam) 
{
	CWizFontsEnumerator* pTHIS = reinterpret_cast<CWizFontsEnumerator*>(lParam);
	return pTHIS->DoEnumStep (lpelfe, lpntme, FontType);
}

void	CWizFontsEnumerator::DoEnumerate (HDC hdc)
{
	ASSERT(NULL != hdc);
	m_aFonts.RemoveAll();

	LOGFONT lf;
	memset (&lf, 0, sizeof(lf));
	lf.lfCharSet	= DEFAULT_CHARSET;
	lf.lfFaceName[0]= 0;
	EnumFontFamiliesEx (hdc, &lf, (FONTENUMPROC)::EnumProc, reinterpret_cast<LPARAM>(this), 0);

#ifdef _DEBUG
	TRACE("\nFound %d fonts:", m_aFonts.GetSize());
	for (int i = 0; i < m_aFonts.GetSize(); i++)
	{
		const Font* p = GetFont(i);
		TRACE("\n %s", (LPCTSTR)(p->Name()));
		for (int j = 0; j < p->GetScriptsCount(); j++)
			TRACE("\n\t %s", (LPCTSTR)(p->GetScript(j)));
	}
#endif

}

void	CWizFontsEnumerator::InternalEnumerate (HDC hdc, bool bWayBack)
{
	// If no valid DC supplied
	if (NULL == hdc && bWayBack)
		{
		TRACE0("Warning! NULL hDC at CWizFontsEnumerator::Enumerate"); 
		// Get main app window (hopefully)
		CClientDC some(NULL);
		//CWnd* pSomeWnd = AfxGetMainWnd();
		InternalEnumerate(some, false); // No way back here again
		}
	else
		DoEnumerate (hdc);
}


void	CWizFontsEnumerator::InternalEnumerate (CDC* pdc,	bool bWayBack)
{
	if (NULL != pdc)
		InternalEnumerate(pdc->m_hAttribDC, bWayBack);
	else
		{
		TRACE0("Warning! NULL pDC at CWizFontsEnumerator::Enumerate");
		if (bWayBack) // try to figure up something
			InternalEnumerate ((HDC)NULL, bWayBack);
		}
}

void	CWizFontsEnumerator::InternalEnumerate (CWnd* pWnd,	bool bWayBack)
{
	if (NULL == pWnd)
		{
		TRACE0("Warning! NULL Window at CWizFontsEnumerator::Enumerate"); 
		if (bWayBack) // try to figure up something
			InternalEnumerate((HDC)NULL, bWayBack);
		}
	else
		{
		// Two attempts to get DC: client DC and, if fails,
		// window DC
		// BLOCK
			{
			CClientDC dc(pWnd);
			if (dc.m_hAttribDC != NULL)
				{
				InternalEnumerate(&dc, bWayBack);
				return;
				}
			}
		// BLOCK
			{
			CWindowDC dc(pWnd);
			InternalEnumerate(&dc, bWayBack);
			}
		}
}

void	CWizFontsEnumerator::Enumerate (HDC hdc)
{
	InternalEnumerate(hdc, true);
}

void	CWizFontsEnumerator::Enumerate (CDC* pdc)
{
	InternalEnumerate(pdc, true);
}

void	CWizFontsEnumerator::Enumerate (CWnd* pWnd)
{
	InternalEnumerate(pWnd, true);
}